home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevadmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  11.5 KB  |  411 lines

  1. /* Copyright (C) 1989, 1995 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevadmp.c,v 1.2 2000/09/19 19:00:11 lpd Exp $*/
  20. /*
  21.  * Apple DMP / Imagewriter driver
  22.  *
  23.  * This is a modification of Mark Wedel's Apple DMP and 
  24.  * Jonathan Luckey's Imagewriter II driver to
  25.  * support the Imagewriter LQ's higher resolution (320x216):
  26.  *      appledmp:  120dpi x  72dpi is still supported (yuck)
  27.  *    iwlo:       160dpi x  72dpi
  28.  *    iwhi:       160dpi x 144dpi
  29.  *      iwlq:      320dpi x 216dpi
  30.  *
  31.  * This is also my first attempt to work with gs. I have not included the LQ's
  32.  * ability to print in colour. Perhaps at a later date I will tackle that.
  33.  *
  34.  * BTW, to get your Imagewriter LQ serial printer to work with a PC, attach it
  35.  * with a nullmodem serial cable.
  36.  *
  37.  * Scott Barker (barkers@cuug.ab.ca)
  38.  */
  39.  
  40. /*
  41.  * This is a modification of Mark Wedel's Apple DMP driver to
  42.  * support 2 higher resolutions:
  43.  *      appledmp:  120dpi x  72dpi is still supported (yuck)
  44.  *    iwlo:       160dpi x  72dpi
  45.  *    iwhi:       160dpi x 144dpi
  46.  *
  47.  * The Imagewriter II is a bit odd.  In pinfeed mode, it thinks its
  48.  * First line is 1 inch from the top of the page. If you set the top
  49.  * form so that it starts printing at the top of the page, and print
  50.  * to near the bottom, it thinks it has run onto the next page and
  51.  * the formfeed will skip a whole page.  As a work around, I reverse
  52.  * the paper about a 1.5 inches at the end of the page before the
  53.  * formfeed to make it think its on the 'right' page.  bah. hack!
  54.  * 
  55.  * This is  my first attempt to work with gs, so your milage may vary
  56.  *
  57.  * Jonathan Luckey (luckey@rtfm.mlb.fl.us)
  58.  */
  59.  
  60. /* This is a bare bones driver I developed for my apple Dot Matrix Printer.
  61.  * This code originally was from the epson driver, but I removed a lot
  62.  * of stuff that was not needed.
  63.  *
  64.  * The Dot Matrix Printer was a predecessor to the apple Imagewriter.  Its
  65.  * main difference being that it was parallel.
  66.  *
  67.  * This code should work fine on Imagewriters, as they have a superset
  68.  * of commands compared to the DMP printer.
  69.  *
  70.  * This driver does not produce the smalles output files possible.  To
  71.  * do that, it should look through the output strings and find repeat
  72.  * occurances of characters, and use the escape sequence that allows
  73.  * printing repeat sequences.  However, as I see it, this the limiting
  74.  * factor in printing is not transmission speed to the printer itself,
  75.  * but rather, how fast the print head can move.  This is assuming the
  76.  * printer is set up with a reasonable speed (9600 bps)
  77.  *
  78.  * WHAT THE CODE DOES AND DOES NOT DO:
  79.  *
  80.  * To print out images, it sets the printer for unidirection printing
  81.  * and 15 cpi (120 dpi). IT sets line feed to 1/9 of an inch (72 dpi).
  82.  * When finished, it sets things back to bidirection print, 1/8" line
  83.  * feeds, and 12 cpi.  There does not appear to be a way to reset
  84.  * things to initial values.
  85.  *
  86.  * This code does not set for 8 bit characters (which is required). It
  87.  * also assumes that carriage return/newline is needed, and not just
  88.  * carriage return.  These are all switch settings on the DMP, and
  89.  * I have configured them for 8 bit data and cr only.
  90.  *
  91.  * You can search for the strings Init and Reset to find the strings
  92.  * that set up the printer and clear things when finished, and change
  93.  * them to meet your needs.
  94.  *
  95.  * Also, you need to make sure that the printer daemon (assuming unix)
  96.  * doesn't change the data as it is being printed.  I have set my
  97.  * printcap file (sunos 4.1.1) with the string:
  98.  * ms=pass8,-opost
  99.  * and it works fine.
  100.  *
  101.  * Feel free to improve this code if you want.  However, please make
  102.  * sure that the old DMP will still be supported by any changes.  This
  103.  * may mean making an imagewriter device, and just copying this file
  104.  * to something like gdevimage.c.
  105.  *
  106.  * The limiting factor of the DMP is the vertical resolution.  However, I
  107.  * see no way to do anything about this.  Horizontal resolution could
  108.  * be increased by using 17 cpi (136 dpi).  I believe the Imagewriter
  109.  * supports 24 cpi (192 dpi).  However, the higher dpi, the slower
  110.  * the printing.
  111.  *
  112.  * Dot Matrix Code by Mark Wedel (master@cats.ucsc.edu)
  113.  */
  114.  
  115.  
  116. #include "gdevprn.h"
  117.  
  118. /* The device descriptors */
  119. private dev_proc_print_page(dmp_print_page);
  120.  
  121. /* Standard DMP device */
  122. gx_device_printer far_data gs_appledmp_device =
  123. prn_device(prn_std_procs, "appledmp",
  124.     85,                /* width_10ths, 8.5" */
  125.     110,                /* height_10ths, 11" */
  126.     120, 72,            /* X_DPI, Y_DPI */
  127.     0, 0.5, 0.5, 0,        /* margins */
  128.     1, dmp_print_page);
  129.  
  130.  
  131. /*  lowrez Imagewriter device */
  132. gx_device_printer far_data gs_iwlo_device =
  133. prn_device(prn_std_procs, "iwlo",
  134.     85,                /* width_10ths, 8.5" */
  135.     110,                /* height_10ths, 11" */
  136.     160, 72,            /* X_DPI, Y_DPI */
  137.     0, 0.5, 0.5, 0,        /* margins */
  138.     1, dmp_print_page);
  139.  
  140.  
  141. /*  hirez Imagewriter device */
  142. gx_device_printer far_data gs_iwhi_device =
  143. prn_device(prn_std_procs, "iwhi",
  144.     85,                /* width_10ths, 8.5" */
  145.     110,                /* height_10ths, 11" */
  146.     160, 144,            /* X_DPI, Y_DPI */
  147.     0, 0.5, 0.5, 0,        /* margins */
  148.     1, dmp_print_page);
  149.  
  150.  
  151. /* LQ hirez Imagewriter device */
  152. gx_device_printer far_data gs_iwlq_device =
  153. prn_device(prn_std_procs, "iwlq",
  154.     85,                /* width_10ths, 8.5" */
  155.     110,                /* height_10ths, 11" */
  156.     320, 216,
  157.     0, 0, 0.5, 0,        /* margins */
  158.     1, dmp_print_page);
  159.  
  160.  
  161. /* ------ Internal routines ------ */
  162.  
  163. #define DMP 1
  164. #define IWLO 2
  165. #define IWHI 3
  166. #define IWLQ 4
  167.  
  168. /* Send the page to the printer. */
  169. private int
  170. dmp_print_page(gx_device_printer *pdev, FILE *prn_stream)
  171. {    
  172.     int dev_type;
  173.  
  174.     int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
  175.     /* Note that in_size is a multiple of 8. */
  176.     int in_size = line_size * 8;
  177.   
  178.     byte *buf1 = (byte *)gs_malloc(in_size, 1, "dmp_print_page(buf1)");
  179.     byte *buf2 = (byte *)gs_malloc(in_size, 1, "dmp_print_page(buf2)");
  180.     byte *prn = (byte *)gs_malloc(3*in_size, 1, "dmp_print_page(prn)");
  181.   
  182.     byte *in = buf1;
  183.     byte *out = buf2;
  184.     int lnum = 0;
  185.  
  186.     /* Check allocations */
  187.     if ( buf1 == 0 || buf2 == 0 || prn == 0 )
  188.     {
  189.         if ( buf1 ) 
  190.             gs_free((char *)buf1, in_size, 1,
  191.             "dmp_print_page(buf1)");
  192.         if ( buf2 ) 
  193.             gs_free((char *)buf2, in_size, 1,
  194.             "dmp_print_page(buf2)");
  195.         if ( prn ) 
  196.             gs_free((char *)prn, in_size, 1,
  197.             "dmp_print_page(prn)");
  198.         return_error(gs_error_VMerror);
  199.     }
  200.  
  201.     if ( pdev->y_pixels_per_inch == 216 )
  202.         dev_type = IWLQ;
  203.     else if ( pdev->y_pixels_per_inch == 144 )
  204.         dev_type = IWHI;
  205.     else if ( pdev->x_pixels_per_inch == 160 )
  206.         dev_type = IWLO;
  207.     else
  208.         dev_type = DMP;
  209.  
  210.     /* Initialize the printer and reset the margins. */
  211.  
  212.     fputs("\r\n\033>\033T16", prn_stream);
  213.  
  214.     switch(dev_type)
  215.     {
  216.     case IWLQ:
  217.         fputs("\033P\033a3", prn_stream);
  218.         break;
  219.     case IWHI:
  220.     case IWLO:
  221.         fputs("\033P", prn_stream);
  222.         break;
  223.     case DMP: 
  224.     default:
  225.         fputs("\033q", prn_stream);
  226.         break;
  227.     }
  228.  
  229.     /* Print lines of graphics */
  230.     while ( lnum < pdev->height )
  231.     {    
  232.         byte *inp;
  233.         byte *in_end;
  234.         byte *out_end;
  235.         int lcnt,ltmp;
  236.         int count, passes;
  237.         byte *prn_blk, *prn_end, *prn_tmp;
  238.  
  239. /* The apple DMP printer seems to be odd in that the bit order on
  240.  * each line is reverse what might be expected.  Meaning, an
  241.  * underscore would be done as a series of 0x80, while on overscore
  242.  * would be done as a series of 0x01.  So we get each
  243.  * scan line in reverse order.
  244.  */
  245.  
  246.         switch (dev_type)
  247.         {
  248.         case IWLQ: passes = 3; break;
  249.         case IWHI: passes = 2; break;
  250.         case IWLO:
  251.         case DMP:
  252.         default: passes = 1; break;
  253.         }
  254.  
  255.         for (count = 0; count < passes; count++)
  256.         {
  257.             for (lcnt=0; lcnt<8; lcnt++)
  258.             {
  259.                 switch(dev_type)
  260.                 {
  261.                 case IWLQ: ltmp = lcnt + 8*count; break;
  262.                 case IWHI: ltmp = 2*lcnt + count; break;
  263.                 case IWLO:
  264.                 case DMP:
  265.                 default: ltmp = lcnt; break;
  266.                 }
  267.  
  268.                 if ((lnum+ltmp)>pdev->height) 
  269.                     memset(in+lcnt*line_size,0,line_size);
  270.                 else
  271.                     gdev_prn_copy_scan_lines(pdev,
  272.                     lnum+ltmp, in + line_size*(7 - lcnt),
  273.                     line_size);
  274.             }
  275.  
  276.             out_end = out;
  277.             inp = in;
  278.             in_end = inp + line_size;
  279.             for ( ; inp < in_end; inp++, out_end += 8 )
  280.             {
  281.                 gdev_prn_transpose_8x8(inp, line_size,
  282.                 out_end, 1);
  283.             }
  284.  
  285.             out_end = out;
  286.  
  287.             switch (dev_type)
  288.             {
  289.             case IWLQ: prn_end = prn + count; break;
  290.             case IWHI: prn_end = prn + in_size*count; break;
  291.             case IWLO:
  292.             case DMP:
  293.             default: prn_end = prn; break;
  294.             }
  295.  
  296.             while ( (int)(out_end-out) < in_size)
  297.             {
  298.                 *prn_end = *(out_end++);
  299.                 if ((dev_type) == IWLQ) prn_end += 3;
  300.                 else prn_end++;
  301.             }
  302.         }
  303.       
  304.         switch (dev_type)
  305.         {
  306.         case IWLQ:
  307.             prn_blk = prn;
  308.             prn_end = prn_blk + in_size * 3;
  309.             while (prn_end > prn && prn_end[-1] == 0 &&
  310.                 prn_end[-2] == 0 && prn_end[-3] == 0)
  311.             {
  312.                 prn_end -= 3;
  313.             }
  314.             while (prn_blk < prn_end && prn_blk[0] == 0 &&
  315.                 prn_blk[1] == 0 && prn_blk[2] == 0)
  316.             {
  317.                 prn_blk += 3;
  318.             }
  319.             if (prn_end != prn_blk)
  320.             {
  321.                 if ((prn_blk - prn) > 7)
  322.                     fprintf(prn_stream,"\033U%04d%c%c%c",
  323.                         (int)((prn_blk - prn)/3),
  324.                         0, 0, 0);
  325.                 else
  326.                     prn_blk = prn;
  327.                 fprintf(prn_stream,"\033C%04d",
  328.                     (int)((prn_end - prn_blk)/3));
  329.                 fwrite(prn_blk, 1, (int)(prn_end - prn_blk),
  330.                     prn_stream);
  331.                 }
  332.             break;
  333.         case IWHI:
  334.             for (count = 0; count < 2; count++)
  335.             {
  336.                 prn_blk = prn_tmp = prn + in_size*count;
  337.                 prn_end = prn_blk + in_size;
  338.                 while (prn_end > prn_blk && prn_end[-1] == 0)
  339.                     prn_end--;
  340.                 while (prn_blk < prn_end && prn_blk[0] == 0)
  341.                     prn_blk++;
  342.                 if (prn_end != prn_blk)
  343.                 {
  344.                     if ((prn_blk - prn_tmp) > 7)
  345.                         fprintf(prn_stream,
  346.                             "\033V%04d%c",
  347.                             (int)(prn_blk-prn_tmp),
  348.                              0);
  349.                     else
  350.                         prn_blk = prn_tmp;
  351.                     fprintf(prn_stream,"\033G%04d",
  352.                         (int)(prn_end - prn_blk));
  353.                     fwrite(prn_blk, 1,
  354.                         (int)(prn_end - prn_blk),
  355.                         prn_stream);
  356.                 }
  357.                 if (!count) fputs("\033T01\r\n",prn_stream);
  358.             }
  359.             fputs("\033T15",prn_stream);
  360.             break;
  361.         case IWLO:
  362.         case DMP:
  363.         default:
  364.             prn_blk = prn;
  365.             prn_end = prn_blk + in_size;
  366.             while (prn_end > prn_blk && prn_end[-1] == 0)
  367.                 prn_end--;
  368.             while (prn_blk < prn_end && prn_blk[0] == 0)
  369.                 prn_blk++;
  370.             if (prn_end != prn_blk)
  371.             {
  372.                 if ((prn_blk - prn) > 7)
  373.                     fprintf(prn_stream,"\033V%04d%c",
  374.                         (int)(prn_blk - prn), 0);
  375.                 else
  376.                     prn_blk = prn;
  377.                 fprintf(prn_stream,"\033G%04d",
  378.                     (int)(prn_end - prn_blk));
  379.                 fwrite(prn_blk, 1, (int)(prn_end - prn_blk),
  380.                     prn_stream);
  381.             }
  382.             break;
  383.         }
  384.  
  385.         fputs("\r\n",prn_stream);
  386.  
  387.         switch (dev_type)
  388.         {
  389.             case IWLQ: lnum += 24 ; break;
  390.             case IWHI: lnum += 16 ; break;
  391.             case IWLO:
  392.             case DMP:
  393.             default: lnum += 8 ; break;
  394.         }
  395.     }
  396.  
  397.     /* ImageWriter will skip a whole page if too close to end */
  398.     /* so skip back more than an inch */
  399.     if ( !(dev_type == DMP) )
  400.         fputs("\033T99\n\n\033r\n\n\n\n\033f", prn_stream);
  401.   
  402.     /* Formfeed and Reset printer */
  403.     fputs("\033T16\f\033<\033B\033E", prn_stream);
  404.     fflush(prn_stream);
  405.  
  406.     gs_free((char *)prn, in_size, 1, "dmp_print_page(prn)");
  407.     gs_free((char *)buf2, in_size, 1, "dmp_print_page(buf2)");
  408.     gs_free((char *)buf1, in_size, 1, "dmp_print_page(buf1)");
  409.     return 0;
  410. }
  411.